#pragma once
#include "../../jMap.h"

template <typename T>
struct _CopyVariantFromAdaptItf {
	static HRESULT copy(VARIANT* p1, const CAdapt< CComPtr<T> >* p2) {
		HRESULT hr = p2->m_T->QueryInterface(IID_IDispatch,
			(void**)&p1->pdispVal);
		if (SUCCEEDED(hr)) {
			p1->vt = VT_DISPATCH;
		}
		else {
			hr = p2->m_T->QueryInterface(IID_IUnknown,
				(void**)&p1->punkVal);
			if( SUCCEEDED(hr) ) {
				p1->vt = VT_UNKNOWN;
			}
		}

		return hr;
	}

	static void init(VARIANT* p) { VariantInit(p); }
	static void destroy(VARIANT* p) { VariantClear(p); }
};

template <typename T>
struct _CopyItfFromAdaptItf {
	static HRESULT copy(T** p1, const CAdapt< CComPtr<T> >* p2) {
		if( *p1 = p2->m_T ) return (*p1)->AddRef(), S_OK;
		return E_POINTER;
	}

	static void init(T** p) {}
	static void destroy(T** p) { if( *p ) (*p)->Release(); }
};
/*
typedef CComEnumOnSTL<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT,
_CopyVariantFromAdaptItf<IGeometry>,list< CAdapt< CComPtr<IGeometry> > > >
CComEnumVariantOnListOfGeometries;

typedef ICollectionOnSTLImpl< IDispatchImpl< IGeometries, &IID_IGeometries >,
list< CAdapt< CComPtr<IGeometry> > >,IGeometry*,_CopyItfFromAdaptItf<IGeometry>,
CComEnumVariantOnListOfGeometries>
IGeometriesCollImpl;

typedef CComEnumOnSTL<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT,
_CopyVariantFromAdaptItf<IBoundingBox>,list< CAdapt< CComPtr<IBoundingBox> > > >
CComEnumVariantOnListOfIBoundingBoxs;

typedef ICollectionOnSTLImpl< IDispatchImpl< IBoundingBoxs, &IID_IBoundingBoxs >,
list< CAdapt< CComPtr<IBoundingBox> > >,IBoundingBox*,_CopyItfFromAdaptItf<IBoundingBox>,
CComEnumVariantOnListOfIBoundingBoxs>
IBoundingBoxsCollImpl;
*/

#define CComEnumVariantOnListOfItemInterface(ItemInterface) \
	CComEnumOnSTL<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT,_CopyVariantFromAdaptItf<ItemInterface>,list< CAdapt< CComPtr<ItemInterface> > > >

#define ClassInterfaceCollImpl(ClassInterface,ItemInterface) \
	ICollectionOnSTLImpl< IDispatchImpl< ClassInterface, &__uuidof(ClassInterface) >,\
	list< CAdapt< CComPtr<ItemInterface> > >,ItemInterface*,_CopyItfFromAdaptItf<ItemInterface>,\
	CComEnumVariantOnListOfItemInterface(ItemInterface)>


#define _DEFINE_COLLECTIONS_(Class,Clsid,ClassInterface,ItemInterface,regID)	\
class ATL_NO_VTABLE Class:\
	public CComObjectRootEx<CComSingleThreadModel>,\
	public CComCoClass<Class,&Clsid>,\
	public ClassInterfaceCollImpl(ClassInterface,ItemInterface)\
{\
public:\
	BEGIN_COM_MAP(Class)\
		COM_INTERFACE_ENTRY2(IDispatch,ClassInterface)\
		COM_INTERFACE_ENTRY(ClassInterface)\
	END_COM_MAP()\
\
	DECLARE_REGISTRY_RESOURCEID(regID)\
\
public:\
	virtual HRESULT __stdcall Add##ItemInterface( \
	ItemInterface *pp##ItemInterface){\
	if( (pp##ItemInterface)!=NULL && !IsBadReadPtr(pp##ItemInterface,sizeof(ItemInterface))) {\
		CComPtr<ItemInterface> sp##ItemInterface = pp##ItemInterface;\
		m_coll.push_back(sp##ItemInterface);\
		return S_OK;\
	}\
\
	return S_FALSE;\
	};\
	ItemInterface * operator[](long index){\
	ItemInterface * _result;\
	get_Item(index,&_result);\
	return _result;\
	}\
	long Clear(){\
		long count = Count();\
		if(count>0){\
			list< CAdapt< CComPtr<ItemInterface> > >::const_iterator iter;\
			for (iter=m_coll.begin();iter!=m_coll.end();iter++)	{\
			CComPtr<ItemInterface>item = (*iter);\
				item.Release();\
			}\
			m_coll.clear();\
		}\
		return count;\
	}\
	Class & operator=(Class & clsref){\
		ATLASSERT(Count()==Clear());\
		ItemInterface* item = NULL;\
		long count = clsref.Count();\
		int i=0;\
		for(i=0;i<count;i++){\
			HRESULT hr = clsref[i]->Clone(&item);\
			CComPtr<ItemInterface> sp##ItemInterface = item;\
			if(SUCCEEDED(hr)){\
				m_coll.push_back(sp##ItemInterface);\
			}\
		}\
			i == count ? 0 : Clear();\
			return *this;\
	}\
	long Count() const{\
		return m_coll.size();\
	}\
	BOOL operator==(Class & clsref)	{	\
		if(Count()!=clsref.Count())		return false;	\
		BOOL isEqual = true;	\
		for (int i=0;i<Count();i++){	(*this)[i]->Equals(clsref[i],&isEqual);	if(isEqual == false) break;	}	\
		return isEqual;	\
	}	\
};

namespace JMap_Geometries{

_DEFINE_COLLECTIONS_(Geometries,CLSID_cmGeometries,IGeometries,IGeometry,IDR_REGPOINT)
_DEFINE_COLLECTIONS_(BoundingBoxes,CLSID_cmBoundingBoxs,IBoundingBoxs,IBoundingBox,IDR_REGPOINT)
_DEFINE_COLLECTIONS_(Polygons,CLSID_cmPolygons,IPolygons,IPolygon,IDR_REGPOINT)
_DEFINE_COLLECTIONS_(LinearRings,CLSID_cmLinearRings,ILinearRings,ILinearRing,IDR_REGPOINT)
_DEFINE_COLLECTIONS_(LineStrings,CLSID_cmLineStrings,ILineStrings,ILineString,IDR_REGPOINT)
_DEFINE_COLLECTIONS_(Points,CLSID_cmPoints,IPoints,IPoint,IDR_REGPOINT)

}